package game;

import java.awt.Color;
import java.awt.Point;
import java.io.*;
import java.util.ArrayList;

import javax.imageio.ImageIO;

public class Level {
	protected File source;
	protected ArrayList<Enemy> enemies;
	protected ArrayList<Field> fields;
	protected ArrayList<Platform> platforms;
	protected ArrayList<ParticleAnimation> animations;
	protected Mario mario;
	protected GrandeCanvas canvas;
	protected Point spawn;
	public boolean disProp = false;
	
	public Level(GrandeCanvas g){
		canvas = g;
		source = new File("levels/base.lvl");
		read();
	}
	
	public Level(GrandeCanvas g, File s){
		source = s;
		enemies = new ArrayList<Enemy>();
		fields = new ArrayList<Field>();
		platforms = new ArrayList<Platform>();
		animations = new ArrayList<ParticleAnimation>();
		canvas = g;
		spawn = new Point(200,200);
		read();
	}
	
	protected void save(){
		ObjectOutputStream out;
		try{
			out = new ObjectOutputStream(new FileOutputStream(source));
			out.writeObject(enemies);
			out.writeObject(fields);
			out.writeObject(platforms);
			out.writeObject(mario);
			out.writeObject(spawn);
			out.close();
		}catch (Exception e){
			System.out.println("Error saving:  ");
			e.printStackTrace();
		}
	}
	
	protected boolean saveAs(String s){
		ObjectOutputStream out;
		try{
			out = new ObjectOutputStream(new FileOutputStream(s));
			out.writeObject(enemies);
			out.writeObject(fields);
			out.writeObject(platforms);
			out.writeObject(mario);
			out.writeObject(spawn);
			out.close();
			return true;
		}catch (Exception e){
			System.out.println("Error saving:  ");
			e.printStackTrace();
			return false;
		}
	}
	
	protected boolean saveAs(File s){
		ObjectOutputStream out;
		try{
			out = new ObjectOutputStream(new FileOutputStream(s));
			out.writeObject(enemies);
			out.writeObject(fields);
			out.writeObject(platforms);
			out.writeObject(mario);
			out.writeObject(spawn);
			out.close();
			return true;
		}catch (Exception e){
			System.out.println("Error saving:  ");
			e.printStackTrace();
			return false;
		}
	}
	
	protected void draw(){
		//draw platforms
		for(Platform i: platforms){
			i.draw();
		}
		for(Enemy e: enemies){
			e.draw();
		}
		try {
			canvas.bufGraphics.drawImage(ImageIO.read(new File("images/shadow.png")), (int)spawn.getX()-canvas.currentX, (int)spawn.getY()-canvas.currentY, mario.curWidth-3, mario.curHeight, canvas);
		} catch (IOException e1) {
		}
		mario.draw();
		for(Field i: fields){
			i.draw();
		}
		for(ParticleAnimation p: animations){
			p.draw();
		}
		canvas.bufGraphics.setColor(Color.black);
		if(disProp){
		canvas.bufGraphics.drawString("Speed: "+mario.fxSpeed, 20, 30);
		canvas.bufGraphics.drawString("Jump Height: "+mario.fxJumpHeight, 20, 50);
		canvas.bufGraphics.drawString("Gravity: "+mario.fxGravity, 20, 70);
		canvas.bufGraphics.drawString("Friction: "+mario.fxFriction, 20, 90);
		canvas.bufGraphics.drawString("xMotion:  "+Math.round(mario.xMotion), 20, 110);
		canvas.bufGraphics.drawString("xPos:  "+mario.x, 20, 130);
		canvas.bufGraphics.drawString("yPos:  "+mario.y, 20, 150);
		}
	}
	
	protected boolean read(){
		try{
			FileInputStream fis = new FileInputStream(source);
			ObjectInputStream in = new ObjectInputStream(fis);
			enemies = (ArrayList<Enemy>)in.readObject();
			fields = (ArrayList<Field>)in.readObject();
			platforms = (ArrayList<Platform>)in.readObject();
			//animations = (ArrayList<ParticleAnimation>)in.readObject();
			animations = new ArrayList<ParticleAnimation>();
			mario = (Mario)in.readObject();
			spawn = (Point)in.readObject();
			in.close();
			fis.close();
			for(Enemy e: enemies){
				e.setLevel(this);
			}
			for(Field e: fields){
				e.setLevel(this);
			}
			for(Platform e:platforms){
				e.setLevel(this);
			}
			mario.setLevel(this);
			return true;
		}catch (Exception e){
			enemies = new ArrayList<Enemy>();
			fields = new ArrayList<Field>();
			platforms = new ArrayList<Platform>();
			animations = new ArrayList<ParticleAnimation>();
			spawn = new Point(200,200);
			mario = new Mario(this, (int)spawn.getX(), (int)spawn.getY());
			return false;
		}
	}
	
	protected void add(Object o){
		if(o instanceof Enemy){
			enemies.add((Enemy)o);
		}else if(o instanceof Field){
			fields.add((Field)o);
		}else if(o instanceof Platform){
			platforms.add((Platform)o);
		}else if(o instanceof ParticleAnimation){
			animations.add((ParticleAnimation)o);
		}
	}
	
	protected void remove(Object o){
		if(o instanceof Enemy){
			enemies.remove((Enemy)o);
		}else if(o instanceof Field){
			fields.remove((Field)o);
		}else if(o instanceof Platform){
			platforms.remove((Platform)o);
		}
	}
	
	public String toString(){
		return "Enemies: "+enemies.size();
	}
	
	public void ChangeSpawn(int x, int y){
		this.spawn = new Point(x -(mario.width),y-(mario.height));
	}
	
	public void toggleProp(){
		if(disProp)
			disProp = false;
		else if(!disProp){
			disProp = true;
		}
	}
}
